/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package moteur.carte.editor;

import moteur.Terrain ;
import moteur.carte.Chemin ;
import moteur.carte.Ville ;
import moteur.carte.Riviere ;
import moteur.carte.Lac ;
import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import javax.swing.JOptionPane;
import moteur.carte.Capitale;
import moteur.carte.Road;
import moteur.partie.Partie;

/**
 *
 * @author sylvain
 */

public class ControllerGraphe {
    private Graphe graphe = new Graphe() ;
    private int cptListeChemin = 0, cptListeVille = 0 ;
    private int cptListeRiviere = 0, cptListeLac = 0 ;
    private int currentListe = 0 ; // permet de se deplacer sur {0: =>Capitale, 1: =>Ville, 2: =>Chemin, 3: =>Riviere, 4: =>Lac}

    // Boolean permettant de définir si l'origine a été ajouté (si c'est le cas il est a false)
    private boolean suiteChemin = true ;
    private boolean suiteRiviere = true ;
    private boolean suiteLac = true ;

    /**
     *
     * @param origDest
     */
    @SuppressWarnings("static-access")
    public Chemin addChemin(Ville origDest) {
        Chemin nChemin;
        if (suiteChemin) {
            nChemin = new Chemin(Terrain.PLAINE) ;
            graphe.addChemin(nChemin);
            graphe.getChemin(cptListeChemin).setOrig((origDest));
            //System.out.println("ajout d'une origine au chemin:"+origDest.getNom());
            suiteChemin = false ;
            return null;

        }
        else {
            nChemin = graphe.getChemin(cptListeChemin++);
            nChemin.setDest((origDest));
            //System.out.println("ajout d'une destination au chemin:"+origDest.getNom());
            suiteChemin = true ;
            return nChemin;
        }


    }

    public Ville addCapitale(float x, float y) {
        Capitale nCapitale = new Capitale() ;
        nCapitale.setNom(Ville.nomsVille[cptListeVille]) ;
        nCapitale.setX(x) ;
        nCapitale.setY(y) ;
        graphe.setCapitale(nCapitale);
        Ville nVille = new Ville() ;
        nVille.setNom(Ville.nomsVille[cptListeVille]) ;
        nVille.setX(x) ;
        nVille.setY(y) ;
        graphe.addVille(nVille);
        cptListeVille++;
        return nCapitale;
    }

    /**
     *
     * @param x
     * @param y
     */
    //@SuppressWarnings("static-access")
    public Ville addVille(float x, float y) {
        Ville nVille = new Ville() ;
        nVille.setNom(Ville.nomsVille[cptListeVille]) ;
        nVille.setX(x) ;
        nVille.setY(y) ;
        graphe.addVille(nVille);
        cptListeVille++;
        return nVille;
    }

    /**
     *
     * @param origDest
     */
    public Riviere addRiviere(Ville origDest) {
        Riviere nRiviere;
        if(suiteRiviere) {
            nRiviere = new Riviere() ;
            graphe.addRiviere(nRiviere);
            graphe.getRiviere(cptListeRiviere).setOrig((origDest));
            //System.out.println("ajout d'une origine a la riviere:"+origDest.getNom());
            suiteRiviere = false ;
        }
        else {
            nRiviere = graphe.getRiviere(cptListeRiviere++);
                    nRiviere.setDest((origDest));
            //System.out.println("ajout d'une destination a la riviere:"+origDest.getNom());
            suiteRiviere = true ;
        }
        return nRiviere;
    }

    /**
     * 
     * @param origDest
     */
    public Lac addLac(Ville origDest) {
        Lac nLac;
        if(suiteLac) {
            nLac = new Lac() ;
            graphe.addLac(nLac);
            graphe.getLac(cptListeLac).getVilles().addElement((origDest));
            //System.out.println("ajout d'une ville au lac:"+origDest.getNom());
            suiteLac = false ;
        }
        else {
            nLac = graphe.getLac(cptListeLac);
            nLac.getVilles().addElement((origDest));
            //System.out.println("ajout d'une autre ville au lac:"+origDest.getNom());
            Object[] options = { "Oui", "Non" };
            int reponse = JOptionPane.showOptionDialog(null, "Voulez vous ajouter une nouvelle ville ?", "Warning",
                JOptionPane.YES_OPTION, JOptionPane.NO_OPTION,
                null, options, options[0]);
	  if (reponse == JOptionPane.NO_OPTION) {
              cptListeLac++;
              suiteLac = true ;
          }
        }
        return nLac;
    }

    /**
     *
     * @param max
     * @return
     */
    public boolean possibleAddCapitale() {
        if (graphe.getCapitale().getX() == 0
                && graphe.getCapitale().getY() == 0)
            return true;
        else
            return false;
    }

    /**
     *
     * @param max
     * @return
     */
    public boolean possibleAddVille(int max) {
        if (cptListeVille >= max)
            return false;
        else
            return true;
    }

    /**
     *
     * @param max
     * @return
     */
    public boolean possibleAddChemin(int max) {
        if (cptListeChemin >= max)
            return false;
        else
            return true;
    }

    /**
     *
     * @param max
     * @return
     */
    public boolean possibleAddRiviere(int max) {
        if (cptListeRiviere >= max)
            return false;
        else
            return true;
    }

    /**
     *
     * @param max
     * @return
     */
    public boolean possibleAddLac(int max) {
        if (cptListeLac >= max)
            return false;
        else
            return true;
    }

    /**
     *
     * @return
     */
    public int getCurrentListe() {
        return currentListe ;
    }

    /**
     *
     */
    public void followTheListe() {
        currentListe++ ;
    }

    /**
     *
     * @param x
     * @param y
     * @return
     */
    public boolean thereIsVilleHere(float x, float y) {
        for (int i = 0 ; i < cptListeVille ; i++) {
            if (this.isBetween(graphe.getVille(i).getX(), x, 0.05f) && this.isBetween(graphe.getVille(i).getY(), y, 0.05f))
                return true;
        }
        return false ;
    }

    /**
     *
     * @param x
     * @param y
     * @return
     */
    public Ville whichVille(float x, float y) {
        for (int i = 0 ; i < cptListeVille ; i++) {
            if (this.isBetween(graphe.getVille(i).getX(), x, 0.05f) && this.isBetween(graphe.getVille(i).getY(), y, 0.05f))
                return graphe.getVille(i);
        }
        return null ;
    }

    /**
     *
     * @return
     */
    public Graphe getGraphe() {
        return graphe ;
    }

    /**
     *
     * @param g
     */
    public void setGraphe(Graphe g) {
        graphe = g ;
    }

    /**
     *
     * @param filename
     * @throws Exception
     */
    public void writeGraphe(String filename) throws Exception{
        XMLEncoder encoder =
           new XMLEncoder(
              new BufferedOutputStream(
                new FileOutputStream(filename)));
        encoder.writeObject(Partie.getInstance().getG());
        encoder.close();
    }

    /**
     *
     * @param filename
     * @throws Exception
     */
    public void readGraphe(String filename) throws Exception {
        File temp = new File("") ;
        File the_file = new File(temp.getAbsolutePath()+File.separator+"src"+File.separator+filename) ;
        XMLDecoder decoder =
            new XMLDecoder(
                new BufferedInputStream(
                    new FileInputStream(the_file)));
        graphe = (Graphe) decoder.readObject();
        decoder.close();
        updateRoads() ;
    }

    /**
     *
     * @param the_file
     * @throws Exception
     */
    public void readGraphe(File the_file) throws Exception {
        XMLDecoder decoder =
            new XMLDecoder(
                new BufferedInputStream(
                    new FileInputStream(the_file)));
        graphe = (Graphe) decoder.readObject();
        decoder.close();
        updateRoads() ;
    }

    public void readGraphe() throws Exception {
        File temp = new File("") ;
        File the_file = new File(getClass().getResource("graphe2.xml").getFile());
        XMLDecoder decoder =
            new XMLDecoder(
                new BufferedInputStream(
                    new FileInputStream(the_file)));
        graphe = (Graphe) decoder.readObject();
        decoder.close();
        updateRoads() ;
    }

    private boolean isBetween(float position, float ref, float interval) {
        //float interval = 50; // 10(largeur de l'objet) + 40. Histoire de ne pas avoir de chevauchement de ville
        if (position <= (ref+interval) && position >= (ref-interval))
            return true;
        else
            return false;
    }

    /**
     *
     * @param x
     * @param y
     * @return
     */
    public boolean paintable(float x, float y) {
        if (cptListeVille > 0) {
            for (int i = 0 ; i < cptListeVille ; i++) {
                if (this.isBetween(graphe.getVille(i).getX(), x, 0.05f) && this.isBetween(graphe.getVille(i).getY(), y, 0.05f))
                    return false;
            }
        }
        return true;
    }

    /**
     *
     */
    public void updateRoads() {
        for (Ville currentVille : graphe.getListeVille()) {
            for (Chemin currentChemin : graphe.getListeChemin()) {
                if (currentChemin.getDest().getNom().equals(currentVille.getNom()) ||
                        currentChemin.getOrig().getNom().equals(currentVille.getNom()))
                    currentVille.add(currentChemin);
            }
            for (Riviere currentRiviere : graphe.getListeRiviere()) {
                if (currentRiviere.getDest().getNom().equals(currentVille.getNom()) ||
                        currentRiviere.getOrig().getNom().equals(currentVille.getNom()))
                    currentVille.add(currentRiviere);
            }
            for (Lac currentLac : graphe.getListeLac()) {
                for(Ville tempVille : graphe.getListeVille()) {
                    if (tempVille.getNom().equals(currentVille.getNom()))
                        currentVille.add(currentLac) ;
                }
            }
        }
    }

    /**
     *
     */
    public void showRoads() {
        for (Ville ville : graphe.getListeVille()) {
            for (Road road : ville.getRoads()) {
                System.out.print(road) ;
            }
            System.out.println();
        }
    }
}
